﻿// ******************************************************************************************************
// <copyright file="select.cs" company="Caroso.inc">
//     Copyright (c) Carlos Osorio All rights reserved.
// </copyright>
// ******************************************************************************************************
// The contents of this file are subject to the Mozilla Public License Version 1.1 (the "License"); 
// you may not use this file except in compliance with the License. You may obtain a copy of the License at 
// http:// www.mozilla.org/MPL/ 
// Software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF 
// ANY KIND, either express or implied. See the License for the specificlanguage governing rights and 
// limitations under the License. 
// 
// 
// 
// The Initial Developer of this version of the Original Code is carlos Osorio carosocali@gmail.com
// 
// Contributor(s): (Open source contributors should list themselves and their modifications here). 
// Change Log: 
// Date           Changed By      Notes
// 22 Nov 2010    Carlos Osorio   Test in StyleCop
// ******************************************************************************************************

namespace GeostatisticalTool.Forms
{
    using System;
    using System.Collections;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Windows.Forms;
    using DotSpatial.Data;
    using DotSpatial.Topology;
    using DotSpatial.Projections;
    using DotSpatial.Controls;
    using GeostatisticalTool.Classes;
    /// <summary>
    /// Create the Form
    /// </summary>
    public partial class Select : Form
    {
        /// <summary>
        /// Denifinition of enviroment Mapwindow
        /// </summary>
        private IMap myMapWin;

        /// <summary>
        /// Shapefile uses in the interpolation
        /// </summary>
        private IFeatureSet shapeLayer;
        
        /// <summary>
        /// Identification of the field that contain the Z value
        /// </summary>
        private int idField;

        /// <summary>
        /// Kriging object
        /// </summary>
        private Kriging mkriging;

        /// <summary>
        /// Manage the display of the all point in the semivariogram
        /// </summary>
        private bool optGra = false;

        /// <summary>
        /// Manage the display of the semivariomgram by Lags
        /// </summary>
        private bool optGraL = false;

        /// <summary>
        /// Manages the display of the theoretical semivariogram
        /// </summary>
        private bool showModel = false;

        /// <summary>
        /// Initializes a new instance of the Select class
        /// </summary>
        public Select()
        {
            this.InitializeComponent();
        }

        /// <summary>
        /// Initializes a new instance of the Select class
        /// </summary>
        /// <param name="mapWin">Global variable of Mapwin</param>
        public Select(IMap mapWin)
        {
            this.myMapWin = mapWin as Map;
            this.InitializeComponent();
            this.pathfile.Text = System.IO.Path.GetTempPath() + "krigtemp.bgd";
        }

        /// <summary>
        ///  Load the form call Select
        /// </summary>
        /// <param name="sender">Sender (object) </param>
        /// <param name="e">Event arguments</param>
        private void Select_Load(object sender, EventArgs e)
        {

            foreach (IMapLayer iLa in this.myMapWin.GetFeatureLayers())
            {
                FeatureSet fT = (FeatureSet)iLa.DataSet;
                if (fT.FeatureType == FeatureType.Point)
                {
                    this.comboBox1.Items.Add(iLa.LegendText);
                }

            }

        }
        
        /// <summary>
        /// Generate a graphic of a semivariogram with all points by default
        /// </summary>
        private void Create_graphic() 
        {
            this.CreateGraphicPar((float)this.mkriging.MaxDistance, (float)this.mkriging.MaxVariance, "ALL", 0, 0);
        }
        
        /// <summary>
        /// Create a graph of a semivariance
        /// </summary>
        /// <param name="maxD">Max. distance in the semivariogram</param>
        /// <param name="maxS">Max semivariance</param>
        /// <param name="typeG">Type of displaying</param>
        /// <param name="lag">length of the lag</param>
        /// <param name="nlags">Number of the lags</param>
        private void CreateGraphicPar(float maxD, float maxS, string typeG, double lag, int nlags) 
        { 
         ////Create an instance of GraphicSemivariogram.cs file.
            GraphicSemivariogram graphicSemivariogram = new GraphicSemivariogram();
            ////Set the height for the graph image.
            graphicSemivariogram.Height = 200;
            ////Set the width for the graph image.
            graphicSemivariogram.Width = 550;
            ////Set the Slices(partition in Axis) for X and Y Axis.
            graphicSemivariogram.XSlice = 35;
            graphicSemivariogram.YSlice = 35;
            ////Set the Title for both Axis.
            graphicSemivariogram.XAxisText = "Distance (m)";
            graphicSemivariogram.YAxisText = "Semiv.";
            graphicSemivariogram.XrealValue = (float)(maxD * 50) / (550 - (2 * 35));
            graphicSemivariogram.YrealValue = (float)(maxS * 50) / (200 - (2 * 35));
            ////Set the Graph Title.;
            graphicSemivariogram.Title = "Semivariogram";
            ////Set the Backcolor and forecolor for the graph title.
            graphicSemivariogram.TitleBackColor = Color.White;
            graphicSemivariogram.TitleForeColor = Color.Black;
            ////Initialize the graph object to draw.
            graphicSemivariogram.InitializeGraph();
            ////Create two array list to  store the points.
            //// string pp;
            ////Create Firstline
            //// GraphicSemivariogram.CreateGraph(Color.LightCyan);
            ArrayList arX;
            ArrayList arY;
            //// Boolean t = false;
            if (typeG == "ALL")
            {
                arX = new ArrayList();
                arY = new ArrayList();
                graphicSemivariogram.XAxis = this.mkriging.Distances();
                graphicSemivariogram.YAxis = this.mkriging.SemiVariances();
            }
            else 
            {
                this.mkriging.CalculateLags(lag, nlags, out arX, out arY);
                graphicSemivariogram.XAxis = arX;
                graphicSemivariogram.YAxis = arY;
            }

            ArrayList arx1;
            ArrayList ary1;
            if (this.showModel) 
            {
                this.mkriging.CalculateModelGraphic(out arx1, out ary1);
                graphicSemivariogram.X1Axis = arx1;
                graphicSemivariogram.Y1Axis = ary1;
                graphicSemivariogram.CreateLines();
            }

            ////Create Second Line.
           graphicSemivariogram.CreateGraph(Color.Red);
            Bitmap bmp = graphicSemivariogram.GetGraph();
            this.pictureBox1.Image = bmp;
            ////bmp.Save(Response.OutputStream,ImageFormat.Jpeg);
        }
       
        /// <summary>
        ///  This function is executed after selection of un item in the ComboBox1
        /// </summary>
        /// <param name="sender">Object (sender)</param>
        /// <param name="e">Events arguments</param>
        private void ComboBox1_SelectedIndexChanged(object sender, EventArgs e)
        {
            bool info = false;
            this.showModel = false;

            this.comboBox2.Items.Clear();
            foreach (IMapLayer iLa in this.myMapWin.GetFeatureLayers())
            {
                FeatureSet fT = (FeatureSet)iLa.DataSet;
                this.shapeLayer = fT;
                if (iLa.LegendText == this.comboBox1.Text)
                {
                    //this.comboBox1.Items.Add(iLa.LegendText);
                    foreach (DataColumn c in fT.DataTable.Columns)
                    {
                        if (c.DataType.ToString() == "System.Double" || c.DataType.ToString() == "System.Int16")
                        {
                            this.comboBox2.Items.Add(c.ColumnName);
                            info = true;
                        }
                    }

                }

            }


            if (info) 
            {
                this.groupBox1.Enabled = true;
                this.groupBox2.Enabled = false;
                this.groupBox3.Enabled = false;
                this.groupBox4.Enabled = false;
               //// pictureBox1.Visible = false;
            }
        }

        /// <summary>
        ///  This function is executed after selection of un item in the ComboBox2
        /// </summary>
        /// <param name="sender">Object (sender)</param>
        /// <param name="e">Events arguments</param>
        private void ComboBox2_SelectedIndexChanged(object sender, EventArgs e)
        {
            this.showModel = false;
            if (this.comboBox2.Text != string.Empty)
            {
                this.idField = 0;
                for (int j = 0; j < this.shapeLayer.DataTable.Columns.Count; j++)
                {
                    if (this.shapeLayer.DataTable.Columns[j].ColumnName == this.comboBox2.Text)
                    {
                        this.idField = j;
                    }
                }

                this.mkriging = new Kriging(this.shapeLayer, this.idField);
                this.pictureBox1.Visible = true;
            }
            else 
            {
                this.groupBox2.Enabled = false;
                this.groupBox3.Enabled = false;
                this.groupBox4.Enabled = false;
                this.pictureBox1.Visible = false;
            }
        }

        /// <summary>
        ///  This function is executed after click over button VerSemi
        /// </summary>
        /// <param name="sender">Object (sender)</param>
        /// <param name="e">Events arguments</param>
        private void VerSemi_Click(object sender, EventArgs e)
        {
            this.groupBox2.Enabled = true;
            this.groupBox3.Enabled = true;
            if (!this.showModel)
            {
                this.mtxrange.Text = Math.Round(this.mkriging.MaxDistance / 2, 2).ToString();
                this.mtxc1.Text = Math.Round(this.mkriging.MaxVariance / 2, 4).ToString();
                this.mtxc0.Text = "0";
            }

            if (this.radioButton1.Checked)
            {
                if (this.optGra == false)
                {
                    this.Create_graphic();
                    this.txbmDist.Text = Math.Round(this.mkriging.MaxDistance, 2).ToString();
                    this.txbmVar.Text = Math.Round(this.mkriging.MaxVariance, 4).ToString();
                    this.txblag.Enabled = false;
                    this.txbnLags.Enabled = false;
                }
                else 
                {
                    this.CreateGraphicPar(float.Parse(this.txbmDist.Text), float.Parse(this.txbmVar.Text), "ALL", 0, 0);
                }
            }
            else 
            {
                if (this.optGraL == false)
                {
                    this.txblag.Enabled = true;
                    this.txbnLags.Enabled = true;
                    this.CreateGraphicPar((float)this.mkriging.MaxDistance, (float)this.mkriging.MaxVariance, "Lag", this.mkriging.MaxDistance * 0.9 / 12, 12);
                    this.txbmDist.Text = Math.Round(this.mkriging.MaxDistance, 2).ToString();
                    this.txbmVar.Text = Math.Round(this.mkriging.MaxVariance, 4).ToString();
                    this.txblag.Text = Math.Round(this.mkriging.MaxDistance * 0.9 / 12, 2).ToString();
                    this.txbnLags.Text = "12";
                }
                else 
                {
                    this.CreateGraphicPar(float.Parse(this.txbmDist.Text), float.Parse(this.txbmVar.Text), "Lag", double.Parse(this.txblag.Text), int.Parse(this.txbnLags.Text));
                }
            }

            double height = Math.Abs(this.shapeLayer.Extent.MaxY - this.shapeLayer.Extent.MinY);
            double width = Math.Abs(this.shapeLayer.Extent.MaxX - this.shapeLayer.Extent.MinX);
            double defaultCellSize = -1;
            if (height <= width)
            {
                defaultCellSize = height / 50;
            }
            else
            {
                defaultCellSize = width / 50;
            }

            this.resolution.Text = Math.Round(defaultCellSize, 4).ToString();
        }

        /// <summary>
        ///  This function is executed after click over button Button1 (apply the model)
        /// </summary>
        /// <param name="sender">Object (sender)</param>
        /// <param name="e">Events arguments</param>
        private void Button1_Click(object sender, EventArgs e)
        {
            IKrigingModel model;
            if ((this.mtxrange.Text != string.Empty) && (this.mtxc0.Text != string.Empty) && (this.mtxc1.Text != string.Empty))
            {
                if (double.Parse(this.mtxrange.Text) == 0)
                {
                    MessageBox.Show("Range must be greater than zero");
                }
                else 
                {
                    switch (this.listBox1.SelectedItems[0].ToString())
                    {
                        case "Gaussian":
                            model = new ModelGaussian();
                            break;
                        case "Circular":
                            model = new ModelCircular();
                            break;
                        case "Exponential":
                                  model = new ModelExponential();
                                 break;
                        case "Spherical":
                                 model = new ModelSpherical();
                                 break;
                        case "Lineal":
                                 model = new ModelLineal();
                                 break;
                        default:
                                 model = new ModelLineal();
                                 break;
                    }

                    model.C0 = double.Parse(this.mtxc0.Text);
                    model.C1 = double.Parse(this.mtxc1.Text);
                    model.Range = double.Parse(this.mtxrange.Text);

                    this.mkriging = new Kriging(this.shapeLayer, this.idField, model);

                    this.showModel = true;
                    this.VerSemi_Click(sender, e);
                    this.groupBox4.Enabled = true;
                }
            }
        }

        /// <summary>
        /// Apply the chages in the graph (Max, min..)
        /// </summary>
        /// <param name="sender">Object (sender)</param>
        /// <param name="e">Events arguments</param>
        private void Apply_Click(object sender, EventArgs e)
        {
            if (this.radioButton1.Checked)
            {
                if (this.optGra == false)
                {
                    this.Create_graphic();
                    this.txbmDist.Text = Math.Round(this.mkriging.MaxDistance, 2).ToString();
                    this.txbmVar.Text = Math.Round(this.mkriging.MaxVariance, 4).ToString();
                    this.txblag.Enabled = false;
                    this.txbnLags.Enabled = false;
                }
                else
                {
                    this.CreateGraphicPar(float.Parse(this.txbmDist.Text), float.Parse(this.txbmVar.Text), "ALL", 0, 0);
                }
            }
            else
            {
                if (this.optGraL == false)
                {
                    this.txblag.Enabled = true;
                    this.txbnLags.Enabled = true;
                    this.CreateGraphicPar((float)this.mkriging.MaxDistance, (float)this.mkriging.MaxVariance, "Lag", this.mkriging.MaxDistance * 0.9 / 12, 12);
                    this.txbmDist.Text = Math.Round(this.mkriging.MaxDistance, 2).ToString();
                    this.txbmVar.Text = Math.Round(this.mkriging.MaxVariance, 4).ToString();
                    this.txblag.Text = Math.Round(this.mkriging.MaxDistance * 0.9 / 12, 2).ToString();
                    this.txbnLags.Text = "12";
                }
                else
                {
                    this.CreateGraphicPar(float.Parse(this.txbmDist.Text), float.Parse(this.txbmVar.Text), "lag", double.Parse(this.txblag.Text), int.Parse(this.txbnLags.Text));
                }
            }
        }

        /// <summary>
        /// Evaluate if there is any change in the value of the Variance
        /// </summary>
        /// <param name="sender">Object (sender)</param>
        /// <param name="e">Events arguments</param>
        private void Txb_mVar_TextChanged(object sender, EventArgs e)
        {
            this.optGra = true;
        }

        /// <summary>
        /// Evaluate if there is any change in the value of the Distance
        /// </summary>
        /// <param name="sender">Object (sender)</param>
        /// <param name="e">Events arguments</param>
        private void Txb_mDist_TextChanged(object sender, EventArgs e)
        {
            this.optGra = true;
        }

        /// <summary>
        /// Evaluate if there is any change in the value of the lag
        /// </summary>
        /// <param name="sender">Object (sender)</param>
        /// <param name="e">Events arguments</param>
        private void Txb_lag_TextChanged(object sender, EventArgs e)
        {
            this.optGraL = true;
        }

        /// <summary>
        /// Evaluate if there is any change in the value of the number of lags
        /// </summary>
        /// <param name="sender">Object (sender)</param>
        /// <param name="e">Events arguments</param>
        private void Txb_nLags_TextChanged(object sender, EventArgs e)
        {
            this.optGraL = true;
        }

        /// <summary>
        /// Evaluate if there is any change in the value of the lag
        /// </summary>
        /// <param name="sender">Object (sender)</param>
        /// <param name="e">Events arguments</param>
        private void Generate_Click(object sender, EventArgs e)
        {

            //Trend t = new Trend(this.shapeLayer, this.idField, 1);
            //IRaster newgrid = t.Surface(this.shapeLayer.Extent, double.Parse(this.resolution.Text), this.shapeLayer.Projection, -32768, "c:\\temp\\t.bgd", int.Parse(this.nPn.Text));

            //Trend t2 = new Trend(this.shapeLayer, this.idField, 2);
            //IRaster newgrid2 = t2.Surface(this.shapeLayer.Extent, double.Parse(this.resolution.Text), this.shapeLayer.Projection, -32768, "c:\\temp\\t2.bgd", int.Parse(this.nPn.Text));

            //Trend t3 = new Trend(this.shapeLayer, this.idField, 3);
            //IRaster newgrid3 = t3.Surface(this.shapeLayer.Extent, double.Parse(this.resolution.Text), this.shapeLayer.Projection, -32768, "c:\\temp\\t3.bgd", int.Parse(this.nPn.Text));

            //this.pathfile.Text = "c:\\temp\\k3.bgd";
            ////ShapeLayer.Projection.ToString()
            this.Cursor = Cursors.WaitCursor;
           // this.mkriging.Search.MaxNumPoints=int.Parse(this.nPn.Text);
            IRaster newgridk = this.mkriging.Surface(
                this.shapeLayer.Extent, double.Parse(this.resolution.Text), this.shapeLayer.Projection, -32768, this.pathfile.Text);

            //this.myMapWin.Layers.Add(newgrid);

            //this.myMapWin.Layers.Add(newgrid2);
            //this.myMapWin.Layers.Add(newgrid3);
             this.myMapWin.Layers.Add(newgridk);
             this.Cursor = Cursors.Default;
            MessageBox.Show(" Ok");
            ////  MyMapWin.Layers.Add(ref newgrid,"Interpolation Kriging");
        }

        /// <summary>
        /// Action to save the file
        /// </summary>
        /// <param name="sender">Object (sender)</param>
        /// <param name="e">Events arguments</param>
        private void Button3_Click(object sender, EventArgs e)
        {
            SaveFileDialog saveDialog = new SaveFileDialog();
            saveDialog.Filter = "Bgd (*.bgd)|*.bgd|Bil (*.bil)|*.bil| asc (*.asc)|*.asc";

            if (saveDialog.ShowDialog() == DialogResult.OK)
            {
                this.pathfile.Text = saveDialog.FileName;
            }
        }

        /// <summary>
        /// It is execute when there is a change in the lisbox1
        /// </summary>
        /// <param name="sender">Object (sender)</param>
        /// <param name="e">Events arguments</param>
        private void ListBox1_SelectedIndexChanged(object sender, EventArgs e)
        {
        }
    }
}
